package com.ruoyi.kanaimqtt.Service.Impl;

import com.alibaba.fastjson.JSONObject;

import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.redis.RedisCache;

import com.ruoyi.common.crc.CrcUtils;

import com.ruoyi.common.utils.MqttLockUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.kanaimqtt.Service.MqttDataWrapperService;
import com.ruoyi.kanaimqtt.Service.MqttGateway;
import com.ruoyi.kanaimqtt.common.BoxWaringUtil;
import com.ruoyi.kanaimqtt.common.WxSendMsgUtil;

import com.ruoyi.kanaimqtt.controller.WebSocketServer;
import com.ruoyi.system.domain.app.*;
import com.ruoyi.system.mapper.CommunityMapper;
import com.ruoyi.system.mapper.CommunityMemberMapper;
import com.ruoyi.system.mapper.PowerBillingMapper;
import com.ruoyi.system.mapper.UserMapper;
import com.ruoyi.system.mapper.app.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.Message;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;


@Slf4j
@Service
@EnableAsync
public class MqttDataWrapperServiceImpl implements MqttDataWrapperService {

    @Autowired
    DeviceMapper deviceMapper;
    @Autowired
    MqttGateway mqttGateway;

    @Value("${sendTopic}")
    private String sendTopic;
    @Autowired
    PowerBillingMapper powerBillingMapper;
    @Autowired
    DeviceSpaceMapper deviceSpaceMapper;
    @Autowired
    MqttLockUtil mqttLockUtil;
    @Autowired
    RechargeOrderMapper rechargeOrderMapper;
    @Autowired
    BoxWaringUtil boxWaringUtil;
    @Autowired
    CardMapper cardMapper;
    @Autowired
    UserMapper userMapper;
    @Autowired
    CommunityMemberMapper communityMemberMapper;
    @Autowired
    PowerCurveMapper powerCurveMapper;
    @Autowired
    CommunityMapper communityMapper;
    @Autowired
    WxSendMsgUtil wxSendMsgUtil;
    @Autowired
    RedisCache redisCache;


    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    @Async("mqttReceiveThreadPool")
    @Override
    public void receiveDataWrapper(Message<?> message) {


        String topic = message.getHeaders().get("mqtt_receivedTopic").toString();
        if (!topic.contains("ElectricHousStatus")) {
            log.info("收到消息topic：topic=[{}]", topic);
        }
        JSONObject payload;
        String[] split = topic.split("/");
        String model = split[4];
        String deviceNum = split[3];
        System.out.println(Arrays.toString(split));
        byte[] bytes = (byte[]) message.getPayload();
        System.out.println(Arrays.toString(bytes));
        System.out.println(bytesToHexString(bytes));

        Device device = deviceMapper.selectByNum(deviceNum);
        try {
            switch (model) {
                case "info": {
                    String imei = hexStringToDesc(analysis(bytes, 1, 20));
                    System.out.println(imei);
                    String iccid = hexStringToDesc(analysis(bytes, 21, 20));
                    System.out.println(iccid);
                    //int crc = Integer.parseInt((analysis(bytes, 21, 20)),16);
                    byte[] bversions = new byte[3];
                    System.arraycopy(bytes, 41, bversions, 0, 3);
                    String versions = byteToString(bversions[0]) + "." + byteToString(bversions[1]) + "." + byteToString(bversions[2]);
                    System.out.println(versions);
                    System.out.println(analysis(bytes, 1, 20));

                    //设备不存在
                    if (StringUtils.isNull(device)) {

                        Device device1 = new Device();
                        device1.setDeviceName(deviceNum);
                        device1.setDeviceNum(deviceNum);
                        device1.setIccid(iccid);
                        device1.setImei(imei);
                        device1.setVersion(versions);
                        deviceMapper.insertSelective(device1);
                        for (int i = 0;i < 2; i++) {
                            DeviceSpace deviceSpace = new DeviceSpace();
                            deviceSpace.setDeviceId(device1.getId());
                            deviceSpace.setSpaceNum(String.valueOf(i+1));
                            deviceSpaceMapper.insertSelective(deviceSpace);
                        }
                        List<PowerBilling> powerBilling1 = powerBillingMapper.getPowerBilling(device.getId());

                        List<PowerBilling> powerBillings=new ArrayList<>();
                        for(int i=0;i<5;i++){
                            PowerBilling billing = new PowerBilling();
                            billing.setMaxPower(0D);
                            billing.setMoney(new BigDecimal(0));
                            powerBillings.add(billing);
                        }
                        for(int i=0;i<powerBilling1.size();i++) {
                            powerBillings.set(i,powerBilling1.get(i));
                        }
                        StringBuilder hex = new StringBuilder();

                        hex.append(String.format("%02x",29));
                        hex.append(String.format("%02x",0));
                        hex.append(String.format("%02x",device.getBillingType()==null ? 0 :device.getBillingType()));
                        //  System.out.println(String.format("%02x",device.getBillingType()==null ? 0 :device.getBillingType()));
                        hex.append(String.format("%04x",device.getElectricityMoney()==null? 0 :device.getElectricityMoney().intValue()*100));
                        //   System.out.println(String.format("%04x",device.getElectricityMoney()==null? 0 :device.getElectricityMoney().intValue()));
                        hex.append(String.format("%04x",device.getTimeBilling()==null? 0:device.getTimeBilling().intValue()*100));
                        //  System.out.println(String.format("%04x",device.getTimeBilling()==null? 0:device.getTimeBilling().intValue()));
                        if(powerBilling1.size()==0){
                            hex.append(String.format("%02x",0));
                            hex.append(String.format("%04x",0));
                            hex.append(String.format("%02x",0));
                            hex.append(String.format("%04x",0));
                            hex.append(String.format("%02x",0));
                            hex.append(String.format("%04x",0));
                            hex.append(String.format("%02x",0));
                            hex.append(String.format("%04x",0));
                            hex.append(String.format("%02x",0));
                            hex.append(String.format("%04x",0));
                        }else {
                            powerBillings.forEach(s->{
                                hex.append(String.format("%02x",s.getMaxPower().intValue()/10));
                                hex.append(String.format("%04x",s.getMoney().intValue()*100));

                            });
                        }
                        hex.append(String.format("%02x",device.getMaxPower()==null? 0 :device.getMaxPower().intValue()/10));
                        //System.out.println(String.format("%02x",device.getMaxPower()==null? 0 :device.getMaxPower().intValue()/10));
                        hex.append(String.format("%02x",device.getCollectionTime()==null? 0 :device.getCollectionTime()));
                        //System.out.println(String.format("%02x",device.getCollectionTime()==null? 0 :device.getCollectionTime()));
                        //                        //hex.append(String.format("%02x",device.getCollectionTime()==null? 0 :device.getCollectionTime()));

                        hex.append(String.format("%02x",device.getPeriodTime()==null? 0 :device.getPeriodTime()));
                        //  System.out.println(String.format("%02x",device.getPeriodTime()==null? 0 :device.getPeriodTime()));
                        hex.append(String.format("%02x",device.getMinPower()==null? 0 :device.getMinPower().intValue()/10));
                        // System.out.println(String.format("%02x",device.getMinPower()==null? 0 :device.getMinPower().intValue()));
                        hex.append(String.format("%02x",device.getContinuePower()==null? 0 :device.getContinuePower()/10));
                        //  System.out.println(String.format("%02x",device.getContinuePower()==null? 0 :device.getContinuePower()));
                        hex.append(String.format("%02x",device.getContinueTime()==null? 0 :device.getEndTime()));
                        // System.out.println(String.format("%02x",device.getContinueTime()==null? 0 :device.getContinueTime()));
                        System.out.println(Arrays.toString(hexString2Bytes(hex.toString())));
                        String crc3 = CrcUtils.getCRC3(hexString2Bytes(hex.toString()));

                        hex.append(reverse(crc3));
                        mqttGateway.sendToMqttBytes(hexString2Bytes(hex.toString()), sendTopic + deviceNum + "/info");
                        return;
                    }
                    //设备禁用
                    if (device.getDeviceState() == 0) {

                        List<PowerBilling> powerBilling1 = powerBillingMapper.getPowerBilling(device.getId());

                        List<PowerBilling> powerBillings=new ArrayList<>();
                        for(int i=0;i<5;i++){
                            PowerBilling billing = new PowerBilling();
                            billing.setMaxPower(0D);
                            billing.setMoney(new BigDecimal(0));
                            powerBillings.add(billing);
                        }
                        for(int i=0;i<powerBilling1.size();i++) {
                            powerBillings.set(i,powerBilling1.get(i));
                        }
                        StringBuilder hex = new StringBuilder();

                        hex.append(String.format("%02x",29));
                        hex.append(String.format("%02x",2));
                        hex.append(String.format("%02x",device.getBillingType()==null ? 0 :device.getBillingType()));
                        //  System.out.println(String.format("%02x",device.getBillingType()==null ? 0 :device.getBillingType()));
                        hex.append(String.format("%04x",device.getElectricityMoney()==null? 0 :device.getElectricityMoney().intValue()*100));
                        //   System.out.println(String.format("%04x",device.getElectricityMoney()==null? 0 :device.getElectricityMoney().intValue()));
                        hex.append(String.format("%04x",device.getTimeBilling()==null? 0:device.getTimeBilling().intValue()*100));
                        //  System.out.println(String.format("%04x",device.getTimeBilling()==null? 0:device.getTimeBilling().intValue()));
                        if(powerBilling1.size()==0){
                            hex.append(String.format("%02x",0));
                            hex.append(String.format("%04x",0));
                            hex.append(String.format("%02x",0));
                            hex.append(String.format("%04x",0));
                            hex.append(String.format("%02x",0));
                            hex.append(String.format("%04x",0));
                            hex.append(String.format("%02x",0));
                            hex.append(String.format("%04x",0));
                            hex.append(String.format("%02x",0));
                            hex.append(String.format("%04x",0));
                        }else {
                            powerBillings.forEach(s->{
                                hex.append(String.format("%02x",s.getMaxPower().intValue()/10));
                                hex.append(String.format("%04x",s.getMoney().intValue()*100));

                            });
                        }
                        hex.append(String.format("%02x",device.getMaxPower()==null? 0 :device.getMaxPower().intValue()/10));
                        //System.out.println(String.format("%02x",device.getMaxPower()==null? 0 :device.getMaxPower().intValue()/10));
                        hex.append(String.format("%02x",device.getCollectionTime()==null? 0 :device.getCollectionTime()));
                        //System.out.println(String.format("%02x",device.getCollectionTime()==null? 0 :device.getCollectionTime()));
                        //                        //hex.append(String.format("%02x",device.getCollectionTime()==null? 0 :device.getCollectionTime()));

                        hex.append(String.format("%02x",device.getPeriodTime()==null? 0 :device.getPeriodTime()));
                        //  System.out.println(String.format("%02x",device.getPeriodTime()==null? 0 :device.getPeriodTime()));
                        hex.append(String.format("%02x",device.getMinPower()==null? 0 :device.getMinPower().intValue()/10));
                        // System.out.println(String.format("%02x",device.getMinPower()==null? 0 :device.getMinPower().intValue()));
                        hex.append(String.format("%02x",device.getContinuePower()==null? 0 :device.getContinuePower()/10));
                        //  System.out.println(String.format("%02x",device.getContinuePower()==null? 0 :device.getContinuePower()));
                        hex.append(String.format("%02x",device.getContinueTime()==null? 0 :device.getEndTime()));
                        // System.out.println(String.format("%02x",device.getContinueTime()==null? 0 :device.getContinueTime()));
                        System.out.println(Arrays.toString(hexString2Bytes(hex.toString())));
                        String crc3 = CrcUtils.getCRC3(hexString2Bytes(hex.toString()));

                        hex.append(reverse(crc3));

                        mqttGateway.sendToMqttBytes(hexString2Bytes(hex.toString()), sendTopic + deviceNum + "/info");
                        return;
                    }
                    device.setIccid(iccid);
                    device.setImei(imei);
                    device.setVersion(versions);
                    List<PowerBilling> powerBilling1 = powerBillingMapper.getPowerBilling(device.getId());

                    List<PowerBilling> powerBillings=new ArrayList<>();
                    for(int i=0;i<5;i++){
                        PowerBilling billing = new PowerBilling();
                        billing.setMaxPower(0D);
                        billing.setMoney(new BigDecimal(0));
                        powerBillings.add(billing);
                    }
                    for(int i=0;i<powerBilling1.size();i++) {
                        powerBillings.set(i,powerBilling1.get(i));
                    }
                    StringBuilder hex = new StringBuilder();

                        hex.append(String.format("%02x",29));
                        hex.append(String.format("%02x",0));
                        hex.append(String.format("%02x",device.getBillingType()==null ? 0 :device.getBillingType()));
                  //  System.out.println(String.format("%02x",device.getBillingType()==null ? 0 :device.getBillingType()));
                        hex.append(String.format("%04x",device.getElectricityMoney()==null? 0 :device.getElectricityMoney().intValue()*100));
                 //   System.out.println(String.format("%04x",device.getElectricityMoney()==null? 0 :device.getElectricityMoney().intValue()));
                        hex.append(String.format("%04x",device.getTimeBilling()==null? 0:device.getTimeBilling().intValue()*100));
                  //  System.out.println(String.format("%04x",device.getTimeBilling()==null? 0:device.getTimeBilling().intValue()));
                        if(powerBilling1.size()==0){
                            hex.append(String.format("%02x",0));
                            hex.append(String.format("%04x",0));
                            hex.append(String.format("%02x",0));
                            hex.append(String.format("%04x",0));
                            hex.append(String.format("%02x",0));
                            hex.append(String.format("%04x",0));
                            hex.append(String.format("%02x",0));
                            hex.append(String.format("%04x",0));
                            hex.append(String.format("%02x",0));
                            hex.append(String.format("%04x",0));
                        }else {
                            powerBillings.forEach(s->{
                                hex.append(String.format("%02x",s.getMaxPower().intValue()/10));
                                hex.append(String.format("%04x",s.getMoney().intValue()*100));

                            });
                        }
                        hex.append(String.format("%02x",device.getMaxPower()==null? 0 :device.getMaxPower().intValue()/10));
                        //System.out.println(String.format("%02x",device.getMaxPower()==null? 0 :device.getMaxPower().intValue()/10));
                        hex.append(String.format("%02x",device.getCollectionTime()==null? 0 :device.getCollectionTime()));
                        //System.out.println(String.format("%02x",device.getCollectionTime()==null? 0 :device.getCollectionTime()));
                    //                        //hex.append(String.format("%02x",device.getCollectionTime()==null? 0 :device.getCollectionTime()));

                        hex.append(String.format("%02x",device.getPeriodTime()==null? 0 :device.getPeriodTime()));
                      //  System.out.println(String.format("%02x",device.getPeriodTime()==null? 0 :device.getPeriodTime()));
                        hex.append(String.format("%02x",device.getMinPower()==null? 0 :device.getMinPower().intValue()/10));
                       // System.out.println(String.format("%02x",device.getMinPower()==null? 0 :device.getMinPower().intValue()));
                        hex.append(String.format("%02x",device.getContinuePower()==null? 0 :device.getContinuePower()/10));
                  //  System.out.println(String.format("%02x",device.getContinuePower()==null? 0 :device.getContinuePower()));
                        hex.append(String.format("%02x",device.getContinueTime()==null? 0 :device.getEndTime()));
                   // System.out.println(String.format("%02x",device.getContinueTime()==null? 0 :device.getContinueTime()));
                    System.out.println(Arrays.toString(hexString2Bytes(hex.toString())));
                    String crc3 = CrcUtils.getCRC3(hexString2Bytes(hex.toString()));

                    hex.append(reverse(crc3));
                   // System.out.println(String.format("%02x",1));

                    //下发设备
                    deviceMapper.updateByPrimaryKeySelective(device);
                    System.out.println(hex);
                    System.out.println(Arrays.toString(hexString2Bytes(hex.toString())));
                    mqttGateway.sendToMqttBytes(hexString2Bytes(hex.toString()), sendTopic + deviceNum + "/info");
                    return;
                }

                case "orderProcess": {
                    System.out.println(Arrays.toString(bytes));
                    Long cardNo = Long.valueOf(analysis(bytes, 5, 4),16) ;
                    log.info("卡号："+cardNo);
                    Long socketNo=Long.valueOf(analysis(bytes, 9, 1),16);
                    log.info("插座号："+socketNo);
                    Long money=Long.valueOf(analysis(bytes, 10, 4),16);
                    log.info("钱数："+money);
                    Long time = Long.valueOf(analysis(bytes, 14, 4),16);
                    log.info("充电时间："+time);
                    Long totalQuantity=Long.valueOf(analysis(bytes, 18, 4),16);
                    log.info("度："+totalQuantity);
                    Long power=Long.valueOf(analysis(bytes, 24, 2),16);
                    log.info("功率："+power);
                    Float v = power.floatValue();
                    if(v>1500F){
                        v=0F;
                    }
                    StringBuilder hex = new StringBuilder();

                    RechargeOrder rechargeOrder = rechargeOrderMapper.selectBySpaceState(device.getId(),socketNo.toString());
                    rechargeOrder.setState(1);
                    rechargeOrder.setRechargeStartTime(rechargeOrder.getCreateTime());
                    rechargeOrder.setOrderState(3);

                    DeviceSpace deviceSpace = deviceSpaceMapper.selectBySpaceId(rechargeOrder.getDeviceId(), Integer.valueOf(rechargeOrder.getHoleNum()));
                    deviceSpace.setState(1);
                    deviceSpaceMapper.updateByPrimaryKeySelective(deviceSpace);
                    rechargeOrder.setPower(String.valueOf(v.intValue()));
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("msgType", "startCharge");
                    WebSocketServer.SendMessage(jsonObject.toJSONString(), rechargeOrder.getUserId() + "");

                    if (rechargeOrder.getState() == 1) {
                        rechargeOrder.setRechargeContinueTime(time/60);
                        rechargeOrder.setRechargeMoney(new BigDecimal(money).divide(new BigDecimal("100")));
                        //log.info("充电钱数：===="+rechargeOrder.getRechargeMoney().toString());
                        rechargeOrder.setRechargeAmount(String.valueOf(totalQuantity.floatValue()/1000));
                        //log.info("充电度数：===="+rechargeOrder.getRechargeAmount());
                        rechargeOrder.setAllMoney(new BigDecimal(money).divide(new BigDecimal("100")));
                        //log.info("充电总钱数：===="+rechargeOrder.getAllMoney().toString());
                        //余额判断
                        if (balanceCheck(rechargeOrder)) {
                            hex.append(String.format("%02x",7));
                            hex.append(String.format("%08x",1));
                            hex.append(String.format("%02x",0));
                            String crc3 = CrcUtils.getCRC3(hexString2Bytes(hex.toString()));
                            hex.append(reverse(crc3));

                            mqttGateway.sendToMqttBytes(hexString2Bytes(hex.toString()), sendTopic + deviceNum + "/status");
                        }else {
                            //返回余额不足 下发设备余额不足 设备上报结束充电
                            hex.append(String.format("%02x",8));
                            hex.append(String.format("%08x",1));
                            hex.append(String.format("%02x",socketNo.intValue()));
                            hex.append(String.format("%02x",0));
                            String crc3 = CrcUtils.getCRC3(hexString2Bytes(hex.toString()));
                            hex.append(reverse(crc3));

                            mqttGateway.sendToMqttBytes(hexString2Bytes(hex.toString()),sendTopic+deviceNum+"/orderStop");
                            return;
                        }
                        //rechargeOrder.setPower(String.valueOf(electricHoleStatus.getPower(electricHoleStatus.getPowerCount()-1)));
                        rechargeOrderMapper.updateByPrimaryKeySelective(rechargeOrder);
                    }else {
                        //返回余额不足 下发设备余额不足 设备上报结束充电
                        hex.append(String.format("%02x",8));
                        hex.append(String.format("%08x",1));
                        hex.append(String.format("%02x",socketNo.intValue()));
                        hex.append(String.format("%02x",0));
                        String crc3 = CrcUtils.getCRC3(hexString2Bytes(hex.toString()));
                        hex.append(reverse(crc3));
                        mqttGateway.sendToMqttBytes(hexString2Bytes(hex.toString()),sendTopic+deviceNum+"/orderStop");
                    }
                    return;
                }
                case "orderStop": {
                    System.out.println(Arrays.toString(bytes));
                    Long socketNo=Long.valueOf(analysis(bytes, 5, 1),16);
                    Long endCause=Long.valueOf(analysis(bytes, 6, 1),16);
                    Long money=Long.valueOf(analysis(bytes, 7, 4),16);
                    Long time=Long.valueOf(analysis(bytes, 11, 4),16);
                    Long totalQuantity=Long.valueOf(analysis(bytes, 15, 4),16);

                    RechargeOrder rechargeOrder = rechargeOrderMapper.selectBySpace(device.getId(),socketNo.toString());

                    if (rechargeOrder!=null && rechargeOrder.getState() != 4) {
                        //订单结束
                            rechargeOrder.setRechargeEndTime(new Date());
                            rechargeOrder.setEndCause(endCause.toString());
                            rechargeOrder.setRechargeContinueTime(time/60);
                            rechargeOrder.setRechargeMoney(new BigDecimal(money).divide(new BigDecimal("100")));
                            rechargeOrder.setRechargeAmount(String.valueOf(totalQuantity.floatValue()/1000));
                            rechargeOrder.setAllMoney(new BigDecimal(money).divide(new BigDecimal("100")));

                            rechargeOrder.setOrderState(4);
                            rechargeOrder.setState(4);

                            rechargeOrderMapper.updateByPrimaryKeySelective(rechargeOrder);
                            //WebSocket下发小程序订单结束
                            //小程序下发订单结束
                            JSONObject jsonObject = new JSONObject();
                            jsonObject.put("msgType", "orderEnd");
                            boolean isSend = WebSocketServer.SendMessage(jsonObject.toJSONString(), rechargeOrder.getUserId() + "");
                            log.info("推送订单结束");

                            //扣款
                            deductMoney(rechargeOrder);
                            //存订单曲线
                            List<PowerCurve> cacheList = redisCache.getCacheList(Constants.RECHARGE_ORDER + rechargeOrder.getOrderNum());
                            if(cacheList!=null && cacheList.size()>0){
                                PowerCurve powerCurve = cacheList.get(cacheList.size() - 1);
                                powerCurveMapper.insert(powerCurve);
                            }

                    }
                    return;
                }


                case "status":{

                    StringBuilder hex = new StringBuilder();
                    hex.append(String.format("%02x",7));
                    hex.append(String.format("%08x",1));
                    hex.append(String.format("%02x",0));
                    String crc3 = CrcUtils.getCRC3(hexString2Bytes(hex.toString()));
                    hex.append(reverse(crc3));
                    System.out.println(hex);
                    Long state1 = Long.valueOf(analysis(bytes, 6, 1));
                    System.out.println(state1);
                    System.out.println(Arrays.toString(bytes));
                    Long state2 = Long.valueOf(analysis(bytes, 7, 1));
                    System.out.println(state2);
                    List<Integer> list=new ArrayList<>(3);
                    list.add(0);
                    list.add(state1.intValue());
                    list.add(state2.intValue());

                    deviceSpaceMapper.updateState(device.getId(),list);


                    mqttGateway.sendToMqttBytes(hexString2Bytes(hex.toString()), sendTopic + deviceNum + "/status");
                    return;

                }case "orderDeviceStop":{
                    Long socketNo=Long.valueOf(analysis(bytes, 5, 1),16);
                    log.info("插座号："+socketNo);
                    System.out.println(Arrays.toString(bytes));
                    Long endCause=Long.valueOf(analysis(bytes, 6, 1),16);
                    Long money=Long.valueOf(analysis(bytes, 7, 4),16);
                    Long time=Long.valueOf(analysis(bytes, 11, 4),16);
                    Long totalQuantity=Long.valueOf(analysis(bytes, 15, 4),16);

                    RechargeOrder rechargeOrder = rechargeOrderMapper.selectBySpaceState(device.getId(),socketNo.toString());

                    if(rechargeOrder !=null && rechargeOrder.getState()==0){
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("msgType", "notRecharge");
                        jsonObject.put("endCause", endCause);
                        WebSocketServer.SendMessage(jsonObject.toJSONString(), rechargeOrder.getUserId() + "");
                        log.info("推送订单未充电");

                        StringBuilder hex = new StringBuilder();
                        hex.append(String.format("%02x",8));
                        hex.append(String.format("%08x",1));
                        hex.append(String.format("%02x",socketNo.intValue()));
                        hex.append(String.format("%02x",0));
                        String crc3 = CrcUtils.getCRC3(hexString2Bytes(hex.toString()));
                        hex.append(reverse(crc3));
                        System.out.println(hex);
                        mqttGateway.sendToMqttBytes(hexString2Bytes(hex.toString()), sendTopic + deviceNum + "/orderDeviceStop");
                        return;
                    }
                    if (rechargeOrder!=null && rechargeOrder.getState() != 4) {
                        //订单结束
                            rechargeOrder.setRechargeEndTime(new Date());
                            rechargeOrder.setEndCause(endCause.toString());
                            rechargeOrder.setRechargeContinueTime(time/60);
                            rechargeOrder.setRechargeMoney(rechargeOrder.getPreinstallMoney());
                            rechargeOrder.setRechargeAmount(String.valueOf(totalQuantity.floatValue()/1000));
                            rechargeOrder.setAllMoney(rechargeOrder.getPreinstallMoney());
                            rechargeOrder.setOrderState(4);
                            rechargeOrder.setState(4);

                            rechargeOrderMapper.updateByPrimaryKeySelective(rechargeOrder);
                            //WebSocket下发小程序订单结束
                            //小程序下发订单结束
                            JSONObject jsonObject = new JSONObject();
                            jsonObject.put("msgType", "orderEnd");
                            boolean isSend = WebSocketServer.SendMessage(jsonObject.toJSONString(), rechargeOrder.getUserId() + "");
                            log.info("推送订单结束");

                            //扣款
                            deductMoney(rechargeOrder);
                            //存订单曲线
                            List<PowerCurve> cacheList = redisCache.getCacheList(Constants.RECHARGE_ORDER + rechargeOrder.getOrderNum());
                            if(cacheList!=null && cacheList.size()>0){
                                PowerCurve powerCurve = cacheList.get(cacheList.size() - 1);
                                powerCurveMapper.insert(powerCurve);
                            }

                    }
                    StringBuilder hex = new StringBuilder();
                    hex.append(String.format("%02x",8));
                    hex.append(String.format("%08x",1));
                    hex.append(String.format("%02x",socketNo.intValue()));
                    hex.append(String.format("%02x",0));
                    String crc3 = CrcUtils.getCRC3(hexString2Bytes(hex.toString()));
                    hex.append(reverse(crc3));
                    System.out.println(hex);
                    mqttGateway.sendToMqttBytes(hexString2Bytes(hex.toString()), sendTopic + deviceNum + "/orderDeviceStop");

                    return;
                }
                case "set":{



                    return;
                }case "orderReply":{
                    return;
                }
                default:
                    return;
            }

        } catch (Exception e) {
            log.info(e.getMessage());
            e.printStackTrace();
        }
    }

    public static String hexStringToDesc(String hex) {
        StringBuilder output = new StringBuilder();
        for (int i = 0; i < hex.length(); i += 2) {
            String str = hex.substring(i, i + 2);
            if (!"00".equals(str)) {
                output.append((char) Integer.parseInt(str, 16));
            }
        }


        return output + "";
    }
    public static String byteToString(byte src) {
        StringBuilder stringBuilder = new StringBuilder("");
        int v = src & 0xFF;
        String hv = Integer.toHexString(v);
        stringBuilder.append(hv);
        return Integer.valueOf(stringBuilder.toString(), 16).toString();
    }
    private void deductMoney(RechargeOrder rechargeOrder) {
        User user = userMapper.selectByPrimaryKey(rechargeOrder.getUserId());
        //余额扣款
        if (rechargeOrder.getPayType() == 1) {
            //订单结束
            Community community = communityMapper.selectByPrimaryKey(rechargeOrder.getCommunityId());
            CommunityMember communityMember = communityMemberMapper.selectByUser(user.getId(), rechargeOrder.getCommunityId());
            //余额通用
            if (StringUtils.isNull(communityMember) || community.getIsBalanceUse() == 1) {
                //扣款
                BigDecimal countMoney = rechargeOrder.getAllMoney();
                log.info("订单金额：" + countMoney);

                List<CommunityMember> communityMembers = communityMemberMapper.getCommunityMembersByOperatorId(user.getId(), rechargeOrder.getOperatorId());
                for (CommunityMember communityMember1 : communityMembers) {

                    if (countMoney.doubleValue() <= communityMember1.getBalance().doubleValue()) {
                        communityMember1.setBalance(communityMember1.getBalance().subtract(countMoney));
                        countMoney = BigDecimal.valueOf(0);
                        log.info("金额小于余额");
                        log.info(communityMember1.getBalance() + "");
                        log.info(communityMember1.getDiscountBalance() + "");
                        log.info(countMoney + "");
                    } else if (countMoney.doubleValue() > communityMember1.getBalance().doubleValue()) {
                        countMoney = countMoney.subtract(communityMember1.getBalance());
                        communityMember1.setBalance(new BigDecimal("0"));
                        log.info("金额大于余额");
                        log.info(communityMember1.getBalance() + "");
                        log.info(communityMember1.getDiscountBalance() + "");
                        log.info(countMoney + "");
                    }
                    if (countMoney.doubleValue() <= communityMember1.getDiscountBalance().doubleValue()) {
                        communityMember1.setDiscountBalance(communityMember1.getDiscountBalance().subtract(countMoney));
                        countMoney = BigDecimal.valueOf(0);
                        log.info("金额小于活动余额");
                        log.info(communityMember1.getBalance() + "");
                        log.info(communityMember1.getDiscountBalance() + "");
                        log.info(countMoney + "");
                    } else if (countMoney.doubleValue() > communityMember1.getDiscountBalance().doubleValue()) {
                        countMoney = countMoney.subtract(communityMember1.getDiscountBalance());
                        communityMember1.setDiscountBalance(new BigDecimal("0"));
                        log.info("金额大于活动余额");
                        log.info(communityMember1.getBalance() + "");
                        log.info(communityMember1.getDiscountBalance() + "");
                        log.info(countMoney + "");
                    }
                    communityMemberMapper.updateByPrimaryKeySelective(communityMember1);
                    if (countMoney.doubleValue() == 0D) {
                        break;
                    }
                }
            }
            // 没开启余额通用
            if (StringUtils.isNotNull(communityMember) && community.getIsBalanceUse() == 0) {
                //余额
                if (rechargeOrder.getPayType() == 1) {
                    //扣款
                    BigDecimal orderMoney = rechargeOrder.getAllMoney();
                    log.info("订单金额" + orderMoney.toPlainString());

                    if (orderMoney.doubleValue() <= communityMember.getBalance().doubleValue()) {
                        communityMember.setBalance(communityMember.getBalance().subtract(orderMoney));
                        log.info("真实金额" + communityMember.getBalance().toPlainString());
                    } else if (orderMoney.doubleValue() <= communityMember.getDiscountBalance().doubleValue()) {
                        communityMember.setDiscountBalance(communityMember.getDiscountBalance().subtract(orderMoney));
                        log.info("活动金额" + communityMember.getDiscountBalance().toPlainString());
                    } else {
                        communityMember.setBalance(communityMember.getBalance().subtract(orderMoney));
                        communityMember.setDiscountBalance(communityMember.getBalance().add(communityMember.getDiscountBalance()));
                        communityMember.setBalance(new BigDecimal("0"));
                    }
                    //余额为负数重置为0
                    if (communityMember.getDiscountBalance().doubleValue() < 0) {
                        communityMember.setDiscountBalance(new BigDecimal("0"));
                    }
                    if (communityMember.getBalance().doubleValue() < 0) {
                        communityMember.setBalance(new BigDecimal("0"));
                    }

                    communityMemberMapper.updateByPrimaryKeySelective(communityMember);
                }

            }
        }
        //电卡
        else if (rechargeOrder.getPayType() == 3) {
            Card card = cardMapper.selectByNum(rechargeOrder.getCardNo());
            //扣款
            BigDecimal orderMoney = rechargeOrder.getAllMoney();
            if (orderMoney.doubleValue() <= card.getDiscountsMoney().doubleValue()) {
                card.setDiscountsMoney(card.getDiscountsMoney().subtract(orderMoney));
            } else if (orderMoney.doubleValue() <= card.getMoney().doubleValue()) {
                card.setMoney(card.getMoney().subtract(orderMoney));
            } else {
                card.setMoney(card.getMoney().subtract(orderMoney));
                card.setDiscountsMoney(card.getDiscountsMoney().add(card.getMoney()));
                card.setMoney(new BigDecimal("0"));
            }
            //余额为负数重置为0
            if (card.getDiscountsMoney().doubleValue() < 0) {
                card.setDiscountsMoney(new BigDecimal("0"));
            }
            if (card.getMoney().doubleValue() < 0) {
                card.setMoney(new BigDecimal("0"));
            }
            cardMapper.updateByPrimaryKeySelective(card);
        }
    }

    /**
     * 余额判断
     *
     * @param rechargeOrder
     */
    private boolean balanceCheck(RechargeOrder rechargeOrder) {

        //临时充电
        if (rechargeOrder.getPayType() == 4 && rechargeOrder.getPreinstallMoney().doubleValue() < rechargeOrder.getAllMoney().doubleValue()) {
            return false;
        }
        //钱包
        else if (rechargeOrder.getPayType() == 1) {
            //余额通用未判断
            CommunityMember communityMember = communityMemberMapper.selectByUser(rechargeOrder.getUserId(), rechargeOrder.getCommunityId());
            if (rechargeOrder.getAllMoney().doubleValue() >= communityMember.getBalance().add(communityMember.getDiscountBalance()).doubleValue()) {
                return false;
            }
        }
        //电卡
        else if (rechargeOrder.getOrderType() == 3) {
            Card card = cardMapper.selectByNum(rechargeOrder.getCardNo());
            if (rechargeOrder.getAllMoney().doubleValue() >= card.getMoney().add(card.getDiscountsMoney()).doubleValue()) {
                return false;
            }
        }
        return true;
    }

    public static String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder("");
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }

    public static String hexStringToString(String s) {
        if (s == null || s.equals("")) {
            return null;
        }
        s = s.replace(" ", "");
        byte[] baKeyword = new byte[s.length() / 2];
        for (int i = 0; i < baKeyword.length; i++) {
            try {
                baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        try {
            s = new String(baKeyword, "UTF-8");
            new String();
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        return s;
    }

    public static String bytetoString(byte[] bytearray) {
        String result = "";
        char temp;

        int length = bytearray.length;
        for (int i = 0; i < length; i++) {
            temp = (char) bytearray[i];
            result += temp;
        }
        return result;
    }

    /**
     * 解析数据
     */
    public static String analysis(byte[] bytes, int srcpos, int length) {
        byte[] bstr = new byte[length];
        try {
            System.arraycopy(bytes, srcpos, bstr, 0, length);
        } catch (Exception e) {
            System.out.println(srcpos + " " + length);
            System.out.println(bytesToHexString(bytes));
        }

        String str = bytesToHexString(bstr);
        return str;
    }

    //把16进制字符串转换成字节数组
    public static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }

    public static byte[] hexString2Bytes(String hex) {

        if ((hex == null) || (hex.equals(""))) {
            return null;
        } else if (hex.length() % 2 != 0) {
            return null;
        } else {
            hex = hex.toUpperCase();
            int len = hex.length() / 2;
            byte[] b = new byte[len];
            char[] hc = hex.toCharArray();
            for (int i = 0; i < len; i++) {
                int p = 2 * i;
                b[i] = (byte) (charToByte(hc[p]) << 4 | charToByte(hc[p + 1]));
            }
            return b;
        }
    }

    public static String reverse(String crc3){
        crc3=crc3.substring(crc3.length()-4);
        String end =crc3.substring(0,2);
        String result=crc3.substring(crc3.length()-2)+end;
        return result.toLowerCase();
    }
}
